Aim

At this experiment we want to determine what political and economic features can correlate with Life Expectancy in different countries and to determine how deeply can they correlate to make some assumptions. We will do this experiment with several features and several countries, and after that we will make some assumptions.

Choosing proper features

Dataset was taken from https://databank.worldbank.org/source/world-development-indicators#

Among 1440 features we have chosen only 42 that could correlate with life expectancy, but after analyzing gained data, we had to get rid of approximately 30 features because of the lack of data. However, we still have some features left that could correlate with chosen parameter:

GDP (per capita), Expense (% of GDP), Tech Industry Progress, Employment Ratio, Waged Workers Ratio, Health Expenditure and Binding Coverage.

Choosing countries

For this experiment we have decided to choose the countries with high-income (USA, Japan), middle-income (Ukraine, Tajikistan) and low-income (Mali, Haiti) to understand on what parameters depends life expectancy in countries with different money capital.

Approach

We will use the linear regression to see if there is a linear relation between the parameters we have chosen and use this knowledge to be able to decide what parameters really affect the life expectancy. Using linear regression we will determine the significance level of every parameter (its p-value), which will tells us either we will reject null hypothesis or no. Also, the R-squared will show us how good our model is. In other words, how good this linear relation is.

Hypothesis

So, we will have two hypothesis’, \(H_0\) (there is no correlation between these parameters) and \(H_1\) (there is at least one parameter that correlates).

\[ H_0 : \beta = \beta_0\ \;\;\;\; H_1: \beta \neq \beta_0 \]

# function to print data of experiment
print_model <- function(model, features) {
  cat("Features:\t", features, "\nR-squared:\t", summary(model)$r.squared,
    "\nP-values:\t", summary(model)$coefficients[,4])
}

Experimenting on High-level countries (USA, Japan)

We will try to find correlation life expectancy using the data set bellow. After this, we will decide what features can be chosen to determine what really effects this parameter of high-level countries. Some of the data is missed, but we do not take the first lines into consideration as we have 50-line data set, where each line corresponds to certain year.

USA

# read csv file
usa <- read.csv(file = 'data/data_usa.csv')
head(usa, 3)

Testing features

model <- lm(formula=life_expectancy ~ tech, data=usa)
print_model(model, "Tech")
Features:    Tech 
R-squared:   0.1488622 
P-values:    3.228643e-12 0.0387192
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=usa)
print_model(model, "Employment Ratio + Expense")
Features:    Employment Ratio + Expense 
R-squared:   0.7191624 
P-values:    7.876299e-18 6.411006e-09 6.106087e-05
model <- lm(formula=life_expectancy ~ waged_workers, data=usa)
print_model(model, "Waged Workers Ratio")
Features:    Waged Workers Ratio 
R-squared:   0.9197001 
P-values:    3.913673e-07 9.298348e-16
model <- lm(formula=life_expectancy ~ health_expenditure, data=usa)
print_model(model, "Health Expenditure")
Features:    Health Expenditure 
R-squared:   0.8958492 
P-values:    3.372309e-25 8.947952e-10
model <- lm(formula=life_expectancy ~ gdp, data=usa)
print_model(model, "GDP per Capita")
Features:    GDP per Capita 
R-squared:   0.9377959 
P-values:    1.892913e-84 2.184632e-29

Japan

# read csv file
japan <- read.csv(file = 'data/data_japan.csv')
head(japan, 3)

Testing features

model <- lm(formula=life_expectancy ~ tech, data=japan)
print_model(model, "Tech")
Features:    Tech 
R-squared:   0.8630052 
P-values:    1.099979e-18 3.60901e-13
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=japan)
print_model(model, "Employment Ratio + Expense")
Features:    Employment Ratio + Expense 
R-squared:   0.4751031 
P-values:    1.916027e-11 0.0004164006 0.8136475
model <- lm(formula=life_expectancy ~ waged_workers, data=japan)
print_model(model, "Waged Workers Ratio")
Features:    Waged Workers Ratio 
R-squared:   0.9765257 
P-values:    2.086609e-22 1.029833e-22
model <- lm(formula=life_expectancy ~ health_expenditure, data=japan)
print_model(model, "Health Expenditure")
Features:    Health Expenditure 
R-squared:   0.8207778 
P-values:    4.332643e-27 9.379517e-08
model <- lm(formula=life_expectancy ~ gdp, data=japan)
print_model(model, "GDP per Capita")
Features:    GDP per Capita 
R-squared:   0.8471802 
P-values:    1.156373e-68 2.18137e-20

Experimenting on Mid-level countries (Ukraine, Tajikistan)

We will try to find correlation life expectancy using the data set bellow. After this, we will decide what features can be chosen to determine what really effects this parameter of mid-level countries. Some of the data is missed, but we do not take the first lines into consideration as we have 50-line data set, where each line corresponds to certain year.

Ukraine

# read csv file
ukraine <- read.csv(file = 'data/data_ukraine.csv')
head(ukraine, 3)

Testing features

model <- lm(formula=life_expectancy ~ tech, data=ukraine)
print_model(model, "Tech")
Features:    Tech 
R-squared:   0.1407207 
P-values:    2.251883e-28 0.04494516
model <- lm(formula=life_expectancy ~ binding_coverage, data=ukraine)
print_model(model, "Binding Coverage")
Features:    Binding Coverage 
R-squared:   0.7469041 
P-values:    0.0003149671 0.0002879277
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=ukraine)
print_model(model, "Employment Ratio + Expense")
Features:    Employment Ratio + Expense 
R-squared:   0.7752642 
P-values:    2.200717e-07 0.004536859 1.831055e-06
model <- lm(formula=life_expectancy ~ waged_workers, data=ukraine)
print_model(model, "Waged Workers Ratio")
Features:    Waged Workers Ratio 
R-squared:   0.4602053 
P-values:    0.7514341 7.262422e-05
model <- lm(formula=life_expectancy ~ health_expenditure, data=ukraine)
print_model(model, "Health Expenditure")
Features:    Health Expenditure 
R-squared:   0.8110302 
P-values:    8.51833e-18 1.47898e-07
model <- lm(formula=life_expectancy ~ gdp, data=ukraine)
print_model(model, "GDP per Capita")
Features:    GDP per Capita 
R-squared:   0.3723871 
P-values:    1.835195e-44 0.0002084853

Tajikistan

# read csv file
tajikistan <- read.csv(file = 'data/data_tajikistan.csv')
head(tajikistan, 3)

Testing features

model <- lm(formula=life_expectancy ~ tech, data=tajikistan)
print_model(model, "Tech")
Features:    Tech 
R-squared:   0.0001222438 
P-values:    6.558978e-12 0.9546065
model <- lm(formula=life_expectancy ~ binding_coverage, data=tajikistan)
print_model(model, "Binding Coverage")
Features:    Binding Coverage 
R-squared:   0.5333738 
P-values:    0.06441052 0.06233742
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=tajikistan)
print_model(model, "Employment Ratio + Expense")
Features:    Employment Ratio + Expense 
R-squared:   0.9748906 
P-values:    0.01706958 0.003234732 0.09977643
model <- lm(formula=life_expectancy ~ waged_workers, data=tajikistan)
print_model(model, "Waged Workers Ratio")
Features:    Waged Workers Ratio 
R-squared:   0.3875586 
P-values:    0.05556629 0.0004036797
model <- lm(formula=life_expectancy ~ health_expenditure, data=tajikistan)
print_model(model, "Health Expenditure")
Features:    Health Expenditure 
R-squared:   0.9049081 
P-values:    1.490146e-18 4.110342e-10
model <- lm(formula=life_expectancy ~ gdp, data=tajikistan)
print_model(model, "GDP per Capita")
Features:    GDP per Capita 
R-squared:   0.650548 
P-values:    8.896529e-30 1.269416e-07

Experimenting on Low-level countries (Mali, Haiti)

We will try to find correlation life expectancy using the data set bellow. After this, we will decide what features can be chosen to determine what really effects this parameter of low-level countries. Some of the data is missed, but we do not take the first lines into consideration as we have 50-line data set, where each line corresponds to certain year.

Mali

# read csv file
mali <- read.csv(file = 'data/data_mali.csv')
head(mali, 3)

Testing features

model <- lm(formula=life_expectancy ~ binding_coverage, data=mali)
print_model(model, "Binding Coverage")
Features:    Binding Coverage 
R-squared:   0.8315655 
P-values:    1.160222e-11 1.410876e-09
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=mali)
print_model(model, "Employment Ratio + Expense")
Features:    Employment Ratio + Expense 
R-squared:   0.2011274 
P-values:    0.003418929 0.3809186 0.07368043
model <- lm(formula=life_expectancy ~ waged_workers, data=mali)
print_model(model, "Waged Workers Ratio")
Features:    Waged Workers Ratio 
R-squared:   0.962084 
P-values:    0.2924288 5.281538e-20
model <- lm(formula=life_expectancy ~ health_expenditure, data=mali)
print_model(model, "Health Expenditure")
Features:    Health Expenditure 
R-squared:   0.5365706 
P-values:    3.879104e-12 0.0003616868
model <- lm(formula=life_expectancy ~ gdp, data=mali)
print_model(model, "GDP per Capita")
Features:    GDP per Capita 
R-squared:   0.8639236 
P-values:    9.028364e-42 1.498146e-21

Haiti

# read csv file
haiti <- read.csv(file = 'data/data_haiti.csv')
head(haiti, 3)

Testing features

model <- lm(formula=life_expectancy ~ tech, data=haiti)
print_model(model, "Tech")
Features:    Tech 
R-squared:   0.3541302 
P-values:    1.231589e-28 0.0006614124
model <- lm(formula=life_expectancy ~ binding_coverage, data=haiti)
print_model(model, "Binding Coverage")
Features:    Binding Coverage 
R-squared:   0.6452332 
P-values:    0.0004200059 0.001650783
model <- lm(formula=life_expectancy ~ employment_ratio, data=haiti)
print_model(model, "Employment Ratio")
Features:    Employment Ratio 
R-squared:   0.4111128 
P-values:    8.24176e-11 0.0002364116
model <- lm(formula=life_expectancy ~ waged_workers, data=haiti)
print_model(model, "Waged Workers Ratio")
Features:    Waged Workers Ratio 
R-squared:   0.9644511 
P-values:    2.658375e-21 2.28196e-20
model <- lm(formula=life_expectancy ~ health_expenditure, data=haiti)
print_model(model, "Health Expenditure")
Features:    Health Expenditure 
R-squared:   0.422701 
P-values:    1.848818e-15 0.00258184
model <- lm(formula=life_expectancy ~ gdp, data=haiti)
print_model(model, "GDP per Capita")
Features:    GDP per Capita 
R-squared:   0.8581152 
P-values:    7.013973e-58 3.930682e-21

Visualization part

In the above part, we have understood that Life expectancy is the most linearly dependent on such features as Health expenditure, Waged workers, GDP per capita, Employment ratio and Expense. It was found out based on the results of the majority of countries, where they are dependent.

Now the main aim of visualization part is to really see, compare the results with graphs, know interesting facts about our and other countries and make sure of the truth of the findings.

require(ggplot2)
library(ggplot2)

library(plotly)

library(dgof) 
library('plot.matrix')

Matrix for tendency of Mean, Mode, Meadian of life expectancy of the countries

Data have been collected through 30-50 years

According to this matrix we can see general tendency of life expectancy of the countries and place them by value of this indicator(starting from longest): Japan, USA, Ukraine, Tajikistan, Haiti, Mali



get_mode <- function(v) {
   uniqv <- unique(v)
   uniqv[which.max(tabulate(match(v, uniqv)))]
}


filenames <- c('data/data_usa.csv', 'data/data_japan.csv',
               'data/data_ukraine.csv', 'data/data_tajikistan.csv',
               'data/data_mali.csv', 'data/data_haiti.csv')

country_names <- c("USA", "Japan", "Ukraine", "Tajikistan", "Mali", "Haiti")
features <- c("_____Mean_____", "_____Mode_____", "_____Median_____")

countries_matrix <- matrix(0, nrow=length(country_names), ncol=length(features),
                          dimnames=list(country_names, features))

# create general data frame for easier visualization
for (i in 1:length(filenames)) {
  df <- read.csv(file = filenames[i])
  df["country"] <- country_names[i]
  
  correlated_df <- df[, c("life_expectancy", "health_expenditure",
                          "waged_workers",  "gdp",
                          "employment_ratio", "expense",
                          "country")]
  
  if (i == 1) {
    general_df <- correlated_df
  }
  else {
    general_df <- rbind(general_df, 
                        correlated_df) 
  }
  
  # clear a column from NaN values
  filtered_list <- na.omit(correlated_df$life_expectancy)
  
  countries_matrix[i, 1] = mean(filtered_list)
  countries_matrix[i, 2] = get_mode(sapply(filtered_list, FUN=round))
  countries_matrix[i, 3] = median(filtered_list)
}

write.csv(general_df, "data/general_df.csv", row.names=FALSE)

print(countries_matrix)
           _____Mean_____ _____Mode_____ _____Median_____
USA              75.77099             75         75.62073
Japan            79.53053             83         79.61171
Ukraine          69.29167             68         69.22172
Tajikistan       61.69115             58         59.25900
Mali             46.77796             47         46.54650
Haiti            55.47958             56         55.67600

Boxplots for comparison of different features

Plotly library also gives you an opportunity to zoom in and

hover over the cursor on the boxplot and see the real numbers (>‿◠)✌

On the below plots we can see that in the majority of the countries Life expectancy really corresponds to our features. Our boxplots show Min, Q1, Median, Q3 and Max characteristics. In some cases, for ex. USA has the biggest Health expenditure, but it does not have the longest life expectacy (it was also found out in predictions of our linear regression for this feature and USA)

p <- ggplot(general_df, aes(country, life_expectancy)) +
  ggtitle("Life expectancy of different countries") +
  labs(y="Years") +
  geom_boxplot(aes(color = country, fill = country), alpha=.5)

ggplotly(p)
Removed 7 rows containing non-finite values (stat_boxplot).

`

p <- ggplot(general_df, aes(country, health_expenditure)) +
  ggtitle("Health expenditure of different countries") +
  labs(y = "Health expenditure") +
  geom_boxplot(aes(color = country, fill = country), alpha=.5)

ggplotly(p)
Removed 181 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, waged_workers)) +
  ggtitle("Waged workers of different countries") +
  labs(y = "% of population") +
  geom_boxplot(aes(color = country, fill = country), alpha=.5)

ggplotly(p)
Removed 120 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, gdp)) +
  ggtitle("GDP of different countries") +
  labs(y = "GDP per capita") +
  geom_boxplot(aes(color = country, fill = country), alpha=.5)

ggplotly(p)
Removed 36 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, expense)) +
  ggtitle("Employment ratio of different countries") +
  labs(y="% of population") +
  geom_boxplot(aes(color = country, fill = country), alpha=.5)

ggplotly(p)
Removed 173 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, expense)) +
  ggtitle("Expense of different countries") +
  labs(y = "Expense") +
  geom_boxplot(aes(color = country, fill = country), alpha=.5)

ggplotly(p)
Removed 173 rows containing non-finite values (stat_boxplot).

Plots for comparison of different densities

For clear understanding, if graph is closer to the right part,

so the feature for such country is bigger :=)

Also like previously, on the below plots we can see that in the majority of the countries Life expectancy really corresponds to our features. Now we explore the density of different features of the countries.

After its investigating we understand that countries with high level of economic development have passed a long way of improvement and make it with small steps, but periodically. On the other hand, countries with less level of development can stay with the same indicators of some features through the years.

p <- ggplot(general_df, aes(x = life_expectancy, fill = country))+
  geom_density(adjust=1.5, alpha=.4) + 
  ggtitle("Life expectancy of different countries") +
  labs(y="Density", x = "Life expectancy")

ggplotly(p)
Removed 7 rows containing non-finite values (stat_density).
p <- ggplot(general_df, aes(x = health_expenditure, fill = country))+
  geom_density(adjust=1.5, alpha=.4) + 
  ggtitle("Health expenditure of different countries") +
  labs(y="Density", x = "Health expenditure")

ggplotly(p)
Removed 181 rows containing non-finite values (stat_density).
p <- ggplot(general_df, aes(x = waged_workers, fill = country))+
  geom_density(adjust=1.5, alpha=.4) + 
  ggtitle("Waged workers of different countries") +
  labs(y="Density", x = "Waged workers")

ggplotly(p)
Removed 120 rows containing non-finite values (stat_density).

You can zoom in if you want to look closer at some plots

USA and Japan have the biggest values of this parameter.

p <- ggplot(general_df, aes(x = gdp, fill = country))+
  geom_density(adjust=1.5, alpha=.4) + 
  ggtitle("GDP of different countries") +
  labs(y="Density", x = "GDP per capita")

ggplotly(p)
Removed 36 rows containing non-finite values (stat_density).

You can zoom in in case you want to look closer at some plots

USA and Japan have the biggest values of this parameter.

p <- ggplot(general_df, aes(x = employment_ratio, fill = country))+
  geom_density(adjust=1.5, alpha=.4) + 
  ggtitle("Employment ratio of different countries") +
  labs(y="Density", x = "Employment ratio") +
  scale_x_continuous(limits=c(-5, 65))

ggplotly(p)
Removed 101 rows containing non-finite values (stat_density).

Here we actually see that partly due to large amount of expense Ukraine has less life expectancy that USA or Japan :=)

p <- ggplot(general_df, aes(x = expense, fill = country))+
  geom_density(adjust=1.5, alpha=.4) + 
  ggtitle("Expense of different countries") +
  labs(y="Density", x = "Expense")

ggplotly(p)
Removed 173 rows containing non-finite values (stat_density).

Exploring if data of Life expectancy of Ukraine follow one of the standard distributions

After exploring the results of Kolmogorov-Smirnov test we can see that our data follow in the majority (we made experiments for it) normal distribution with mean = mean(country_df$life_expectancy) and sd = sd(country_df$life_expectancy). However, uniform distribution with min = min(country_df$life_expectancy) and max = max(country_df$life_expectancy) also is pretty close.

It was proved with below visualizations.

library(tolerance)
country_df <- read.csv(file = 'data/data_ukraine.csv')

filtered_list <- na.omit(country_df$life_expectancy)

len_list <- length(filtered_list)

compare_norm <- rnorm(len_list, mean=mean(filtered_list), 
                      sd=sd(filtered_list))
compare_exp <- r2exp(len_list, shift=min(filtered_list))
compare_unif <- runif(len_list, min = min(filtered_list), max = max(filtered_list))

ks.test(filtered_list, compare_norm)

    Two-sample Kolmogorov-Smirnov test

data:  filtered_list and compare_norm
D = 0.10417, p-value = 0.9602
alternative hypothesis: two-sided
ks.test(filtered_list, compare_exp)

    Two-sample Kolmogorov-Smirnov test

data:  filtered_list and compare_exp
D = 0.60417, p-value = 1.745e-08
alternative hypothesis: two-sided
ks.test(filtered_list, compare_unif)

    Two-sample Kolmogorov-Smirnov test

data:  filtered_list and compare_unif
D = 0.16667, p-value = 0.5221
alternative hypothesis: two-sided
library(lattice)
library(latticeExtra)

vals <- data.frame(feature=filtered_list,
                   norm_distr=compare_norm)

ecdfplot(~ feature + norm_distr, data=vals, auto.key=list(space='right'))

vals <- data.frame(feature=filtered_list,
                   exp_distr=compare_exp)

ecdfplot(~ feature + exp_distr, data=vals, auto.key=list(space='right'))

vals <- data.frame(feature=filtered_list,
                   unif_distr=compare_unif)

ecdfplot(~ feature + unif_distr, data=vals, auto.key=list(space='right'))

Conclusion

So, what we can see is that for every country the importance of some features may differ, take for example Tech, this feature is very significant in “Tech-countries” such as Japan and, as we can see, there is some linear relation between Life Expectancy and Tech industry there, but not for other countries. The same we can say about Binding Coverage as in High-Income Countries this parameter is always almost the same, which doesn’t show any linear relation, but this does not mean that it is insignificant (at least not for countries, but for our model).

We have covered what parameters do not give us any possibility to estimate Life Expectancy, let’s talt about the parameters, that have shown us a good linear relation. These are:

  1. Waged Workers Ratio (0.77 goodness of fit on average)
  2. GDP (0.75 goodness of fit on average)
  3. Health Expenditure (0.72 goodness of fit on average)
  4. Employment Ratio + Expense (0.6 goodness of fit on average)

Of course, these estimations are not very accurate because of the lack of data, but at least we can see that there is some relation between these parameters and life expectancy and it’s clear as everything reduces to if country can provide its residents with work, medicine and good finance capital (which depends on job), then those people can cover all their need to live long and healthy life.

LS0tDQp0aXRsZTogIlJlc2VhcmNoIHByb2plY3QiDQphdXRob3I6ICJEZW55cyBIZXJhc3ltdWsgYW5kIFlhcm9zbGF2IE1vcm96ZXZ5Y2giDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyBBaW0NCg0KQXQgdGhpcyBleHBlcmltZW50IHdlIHdhbnQgdG8gZGV0ZXJtaW5lICoqd2hhdCBwb2xpdGljYWwgYW5kIGVjb25vbWljIGZlYXR1cmVzKiogY2FuIGNvcnJlbGF0ZSB3aXRoICoqTGlmZSBFeHBlY3RhbmN5KiogaW4gZGlmZmVyZW50IGNvdW50cmllcyBhbmQgdG8gZGV0ZXJtaW5lIGhvdyBkZWVwbHkgY2FuIHRoZXkgY29ycmVsYXRlIHRvIG1ha2Ugc29tZSBhc3N1bXB0aW9ucy4gV2Ugd2lsbCBkbyB0aGlzIGV4cGVyaW1lbnQgd2l0aCBzZXZlcmFsIGZlYXR1cmVzIGFuZCBzZXZlcmFsIGNvdW50cmllcywgYW5kIGFmdGVyIHRoYXQgd2Ugd2lsbCBtYWtlIHNvbWUgYXNzdW1wdGlvbnMuDQoNCiMjIENob29zaW5nIHByb3BlciBmZWF0dXJlcw0KDQpEYXRhc2V0IHdhcyB0YWtlbiBmcm9tIGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9zb3VyY2Uvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycyMgDQoNCkFtb25nIDE0NDAgZmVhdHVyZXMgd2UgaGF2ZSBjaG9zZW4gb25seSA0MiB0aGF0IGNvdWxkIGNvcnJlbGF0ZSB3aXRoIGxpZmUgZXhwZWN0YW5jeSwgYnV0IGFmdGVyIGFuYWx5emluZyBnYWluZWQgZGF0YSwgd2UgaGFkIHRvIGdldCByaWQgb2YgYXBwcm94aW1hdGVseSAzMCBmZWF0dXJlcyBiZWNhdXNlIG9mIHRoZSBsYWNrIG9mIGRhdGEuIEhvd2V2ZXIsIHdlIHN0aWxsIGhhdmUgc29tZSBmZWF0dXJlcyBsZWZ0IHRoYXQgY291bGQgY29ycmVsYXRlIHdpdGggY2hvc2VuIHBhcmFtZXRlcjoNCg0KKipHRFAgKHBlciBjYXBpdGEpKiosICoqRXhwZW5zZSAoJSBvZiBHRFApKiosICoqVGVjaCBJbmR1c3RyeSBQcm9ncmVzcyoqLCAqKkVtcGxveW1lbnQgUmF0aW8qKiwgKipXYWdlZCBXb3JrZXJzIFJhdGlvKiosICoqSGVhbHRoIEV4cGVuZGl0dXJlKiogYW5kICoqQmluZGluZyBDb3ZlcmFnZSoqLg0KDQojIyBDaG9vc2luZyBjb3VudHJpZXMNCg0KRm9yIHRoaXMgZXhwZXJpbWVudCB3ZSBoYXZlIGRlY2lkZWQgdG8gY2hvb3NlIHRoZSBjb3VudHJpZXMgd2l0aCBoaWdoLWluY29tZSAoVVNBLCBKYXBhbiksIG1pZGRsZS1pbmNvbWUgKFVrcmFpbmUsIFRhamlraXN0YW4pIGFuZCBsb3ctaW5jb21lIChNYWxpLCBIYWl0aSkgdG8gdW5kZXJzdGFuZCBvbiB3aGF0IHBhcmFtZXRlcnMgZGVwZW5kcyBsaWZlIGV4cGVjdGFuY3kgaW4gY291bnRyaWVzIHdpdGggZGlmZmVyZW50IG1vbmV5IGNhcGl0YWwuDQoNCiMjIEFwcHJvYWNoDQoNCldlIHdpbGwgdXNlIHRoZSBsaW5lYXIgcmVncmVzc2lvbiB0byBzZWUgaWYgdGhlcmUgaXMgYSBsaW5lYXIgcmVsYXRpb24gYmV0d2VlbiB0aGUgcGFyYW1ldGVycyB3ZSBoYXZlIGNob3NlbiBhbmQgdXNlIHRoaXMga25vd2xlZGdlIHRvIGJlIGFibGUgdG8gZGVjaWRlIHdoYXQgcGFyYW1ldGVycyByZWFsbHkgYWZmZWN0IHRoZSBsaWZlIGV4cGVjdGFuY3kuIFVzaW5nIGxpbmVhciByZWdyZXNzaW9uIHdlIHdpbGwgZGV0ZXJtaW5lIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgZXZlcnkgcGFyYW1ldGVyIChpdHMgcC12YWx1ZSksIHdoaWNoIHdpbGwgdGVsbHMgdXMgZWl0aGVyIHdlIHdpbGwgcmVqZWN0IG51bGwgaHlwb3RoZXNpcyBvciBuby4gQWxzbywgdGhlIFItc3F1YXJlZCB3aWxsIHNob3cgdXMgaG93IGdvb2Qgb3VyIG1vZGVsIGlzLiBJbiBvdGhlciB3b3JkcywgaG93IGdvb2QgdGhpcyBsaW5lYXIgcmVsYXRpb24gaXMuDQoNCiMjIEh5cG90aGVzaXMNCg0KU28sIHdlIHdpbGwgaGF2ZSB0d28gaHlwb3RoZXNpcycsICRIXzAkICh0aGVyZSBpcyBubyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZXNlIHBhcmFtZXRlcnMpIGFuZCAkSF8xJCAodGhlcmUgaXMgYXQgbGVhc3Qgb25lIHBhcmFtZXRlciB0aGF0IGNvcnJlbGF0ZXMpLg0KDQokJA0KICBIXzAgOiBcYmV0YSA9IFxiZXRhXzBcICAgXDtcO1w7XDsgSF8xOiBcYmV0YSBcbmVxIFxiZXRhXzANCiQkDQoNCmBgYHtyfQ0KIyBmdW5jdGlvbiB0byBwcmludCBkYXRhIG9mIGV4cGVyaW1lbnQNCnByaW50X21vZGVsIDwtIGZ1bmN0aW9uKG1vZGVsLCBmZWF0dXJlcykgew0KICBjYXQoIkZlYXR1cmVzOlx0IiwgZmVhdHVyZXMsICJcblItc3F1YXJlZDpcdCIsIHN1bW1hcnkobW9kZWwpJHIuc3F1YXJlZCwNCiAgICAiXG5QLXZhbHVlczpcdCIsIHN1bW1hcnkobW9kZWwpJGNvZWZmaWNpZW50c1ssNF0pDQp9DQpgYGANCg0KIyMgRXhwZXJpbWVudGluZyBvbiBIaWdoLWxldmVsIGNvdW50cmllcyAoVVNBLCBKYXBhbikNCg0KV2Ugd2lsbCB0cnkgdG8gZmluZCBjb3JyZWxhdGlvbiAqKmxpZmUgZXhwZWN0YW5jeSoqIHVzaW5nIHRoZSBkYXRhIHNldCBiZWxsb3cuIEFmdGVyIHRoaXMsIHdlIHdpbGwgZGVjaWRlIHdoYXQgZmVhdHVyZXMgY2FuIGJlIGNob3NlbiB0byBkZXRlcm1pbmUgd2hhdCByZWFsbHkgZWZmZWN0cyB0aGlzIHBhcmFtZXRlciBvZiBoaWdoLWxldmVsIGNvdW50cmllcy4gKlNvbWUgb2YgdGhlIGRhdGEgaXMgbWlzc2VkLCBidXQgd2UgZG8gbm90IHRha2UgdGhlIGZpcnN0IGxpbmVzIGludG8gY29uc2lkZXJhdGlvbiBhcyB3ZSBoYXZlIDUwLWxpbmUgZGF0YSBzZXQsIHdoZXJlIGVhY2ggbGluZSBjb3JyZXNwb25kcyB0byBjZXJ0YWluIHllYXIuKg0KDQoNCiMjIyBVU0ENCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCnVzYSA8LSByZWFkLmNzdihmaWxlID0gJ2RhdGEvZGF0YV91c2EuY3N2JykNCmhlYWQodXNhLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT11c2EpDQpwcmludF9tb2RlbChtb2RlbCwgIlRlY2giKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGVtcGxveW1lbnRfcmF0aW8gKyBleHBlbnNlLCBkYXRhPXVzYSkNCnByaW50X21vZGVsKG1vZGVsLCAiRW1wbG95bWVudCBSYXRpbyArIEV4cGVuc2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IHdhZ2VkX3dvcmtlcnMsIGRhdGE9dXNhKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJXYWdlZCBXb3JrZXJzIFJhdGlvIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBoZWFsdGhfZXhwZW5kaXR1cmUsIGRhdGE9dXNhKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT11c2EpDQpwcmludF9tb2RlbChtb2RlbCwgIkdEUCBwZXIgQ2FwaXRhIikNCmBgYA0KDQojIyMgSmFwYW4NCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCmphcGFuIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX2phcGFuLmNzdicpDQpoZWFkKGphcGFuLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT1qYXBhbikNCnByaW50X21vZGVsKG1vZGVsLCAiVGVjaCIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZW1wbG95bWVudF9yYXRpbyArIGV4cGVuc2UsIGRhdGE9amFwYW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkVtcGxveW1lbnQgUmF0aW8gKyBFeHBlbnNlIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiB3YWdlZF93b3JrZXJzLCBkYXRhPWphcGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJXYWdlZCBXb3JrZXJzIFJhdGlvIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBoZWFsdGhfZXhwZW5kaXR1cmUsIGRhdGE9amFwYW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkhlYWx0aCBFeHBlbmRpdHVyZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZ2RwLCBkYXRhPWphcGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJHRFAgcGVyIENhcGl0YSIpDQpgYGANCg0KIyMgRXhwZXJpbWVudGluZyBvbiBNaWQtbGV2ZWwgY291bnRyaWVzIChVa3JhaW5lLCBUYWppa2lzdGFuKQ0KDQpXZSB3aWxsIHRyeSB0byBmaW5kIGNvcnJlbGF0aW9uICoqbGlmZSBleHBlY3RhbmN5KiogdXNpbmcgdGhlIGRhdGEgc2V0IGJlbGxvdy4gQWZ0ZXIgdGhpcywgd2Ugd2lsbCBkZWNpZGUgd2hhdCBmZWF0dXJlcyBjYW4gYmUgY2hvc2VuIHRvIGRldGVybWluZSB3aGF0IHJlYWxseSBlZmZlY3RzIHRoaXMgcGFyYW1ldGVyIG9mIG1pZC1sZXZlbCBjb3VudHJpZXMuICpTb21lIG9mIHRoZSBkYXRhIGlzIG1pc3NlZCwgYnV0IHdlIGRvIG5vdCB0YWtlIHRoZSBmaXJzdCBsaW5lcyBpbnRvIGNvbnNpZGVyYXRpb24gYXMgd2UgaGF2ZSA1MC1saW5lIGRhdGEgc2V0LCB3aGVyZSBlYWNoIGxpbmUgY29ycmVzcG9uZHMgdG8gY2VydGFpbiB5ZWFyLioNCg0KIyMjIFVrcmFpbmUNCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCnVrcmFpbmUgPC0gcmVhZC5jc3YoZmlsZSA9ICdkYXRhL2RhdGFfdWtyYWluZS5jc3YnKQ0KaGVhZCh1a3JhaW5lLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT11a3JhaW5lKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJUZWNoIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBiaW5kaW5nX2NvdmVyYWdlLCBkYXRhPXVrcmFpbmUpDQpwcmludF9tb2RlbChtb2RlbCwgIkJpbmRpbmcgQ292ZXJhZ2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGVtcGxveW1lbnRfcmF0aW8gKyBleHBlbnNlLCBkYXRhPXVrcmFpbmUpDQpwcmludF9tb2RlbChtb2RlbCwgIkVtcGxveW1lbnQgUmF0aW8gKyBFeHBlbnNlIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiB3YWdlZF93b3JrZXJzLCBkYXRhPXVrcmFpbmUpDQpwcmludF9tb2RlbChtb2RlbCwgIldhZ2VkIFdvcmtlcnMgUmF0aW8iKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGhlYWx0aF9leHBlbmRpdHVyZSwgZGF0YT11a3JhaW5lKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT11a3JhaW5lKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJHRFAgcGVyIENhcGl0YSIpDQpgYGANCg0KIyMjIFRhamlraXN0YW4NCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCnRhamlraXN0YW4gPC0gcmVhZC5jc3YoZmlsZSA9ICdkYXRhL2RhdGFfdGFqaWtpc3Rhbi5jc3YnKQ0KaGVhZCh0YWppa2lzdGFuLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT10YWppa2lzdGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJUZWNoIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBiaW5kaW5nX2NvdmVyYWdlLCBkYXRhPXRhamlraXN0YW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkJpbmRpbmcgQ292ZXJhZ2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGVtcGxveW1lbnRfcmF0aW8gKyBleHBlbnNlLCBkYXRhPXRhamlraXN0YW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkVtcGxveW1lbnQgUmF0aW8gKyBFeHBlbnNlIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiB3YWdlZF93b3JrZXJzLCBkYXRhPXRhamlraXN0YW4pDQpwcmludF9tb2RlbChtb2RlbCwgIldhZ2VkIFdvcmtlcnMgUmF0aW8iKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGhlYWx0aF9leHBlbmRpdHVyZSwgZGF0YT10YWppa2lzdGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT10YWppa2lzdGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJHRFAgcGVyIENhcGl0YSIpDQpgYGANCg0KIyMgRXhwZXJpbWVudGluZyBvbiBMb3ctbGV2ZWwgY291bnRyaWVzIChNYWxpLCBIYWl0aSkNCg0KV2Ugd2lsbCB0cnkgdG8gZmluZCBjb3JyZWxhdGlvbiAqKmxpZmUgZXhwZWN0YW5jeSoqIHVzaW5nIHRoZSBkYXRhIHNldCBiZWxsb3cuIEFmdGVyIHRoaXMsIHdlIHdpbGwgZGVjaWRlIHdoYXQgZmVhdHVyZXMgY2FuIGJlIGNob3NlbiB0byBkZXRlcm1pbmUgd2hhdCByZWFsbHkgZWZmZWN0cyB0aGlzIHBhcmFtZXRlciBvZiBsb3ctbGV2ZWwgY291bnRyaWVzLiAqU29tZSBvZiB0aGUgZGF0YSBpcyBtaXNzZWQsIGJ1dCB3ZSBkbyBub3QgdGFrZSB0aGUgZmlyc3QgbGluZXMgaW50byBjb25zaWRlcmF0aW9uIGFzIHdlIGhhdmUgNTAtbGluZSBkYXRhIHNldCwgd2hlcmUgZWFjaCBsaW5lIGNvcnJlc3BvbmRzIHRvIGNlcnRhaW4geWVhci4qDQoNCiMjIyBNYWxpDQoNCmBgYHtyfQ0KIyByZWFkIGNzdiBmaWxlDQptYWxpIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX21hbGkuY3N2JykNCmhlYWQobWFsaSwgMykNCmBgYA0KDQojIyMjIFRlc3RpbmcgZmVhdHVyZXMNCg0KYGBge3J9DQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGJpbmRpbmdfY292ZXJhZ2UsIGRhdGE9bWFsaSkNCnByaW50X21vZGVsKG1vZGVsLCAiQmluZGluZyBDb3ZlcmFnZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZW1wbG95bWVudF9yYXRpbyArIGV4cGVuc2UsIGRhdGE9bWFsaSkNCnByaW50X21vZGVsKG1vZGVsLCAiRW1wbG95bWVudCBSYXRpbyArIEV4cGVuc2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IHdhZ2VkX3dvcmtlcnMsIGRhdGE9bWFsaSkNCnByaW50X21vZGVsKG1vZGVsLCAiV2FnZWQgV29ya2VycyBSYXRpbyIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gaGVhbHRoX2V4cGVuZGl0dXJlLCBkYXRhPW1hbGkpDQpwcmludF9tb2RlbChtb2RlbCwgIkhlYWx0aCBFeHBlbmRpdHVyZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZ2RwLCBkYXRhPW1hbGkpDQpwcmludF9tb2RlbChtb2RlbCwgIkdEUCBwZXIgQ2FwaXRhIikNCmBgYA0KDQojIyMgSGFpdGkNCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCmhhaXRpIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX2hhaXRpLmNzdicpDQpoZWFkKGhhaXRpLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiVGVjaCIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gYmluZGluZ19jb3ZlcmFnZSwgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiQmluZGluZyBDb3ZlcmFnZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZW1wbG95bWVudF9yYXRpbywgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiRW1wbG95bWVudCBSYXRpbyIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gd2FnZWRfd29ya2VycywgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiV2FnZWQgV29ya2VycyBSYXRpbyIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gaGVhbHRoX2V4cGVuZGl0dXJlLCBkYXRhPWhhaXRpKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiR0RQIHBlciBDYXBpdGEiKQ0KYGBgDQoNCiMgVmlzdWFsaXphdGlvbiBwYXJ0DQoNCkluIHRoZSBhYm92ZSBwYXJ0LCB3ZSBoYXZlIHVuZGVyc3Rvb2QgdGhhdCAqKkxpZmUgZXhwZWN0YW5jeSoqIGlzIHRoZSBtb3N0IGxpbmVhcmx5IGRlcGVuZGVudCBvbiBzdWNoIGZlYXR1cmVzIGFzICoqSGVhbHRoIGV4cGVuZGl0dXJlKiosICoqV2FnZWQgd29ya2VycyoqLCAgKipHRFAgcGVyIGNhcGl0YSoqLCAqKkVtcGxveW1lbnQgcmF0aW8qKiBhbmQgKipFeHBlbnNlKiouIEl0IHdhcyBmb3VuZCBvdXQgYmFzZWQgb24gdGhlIHJlc3VsdHMgb2YgdGhlIG1ham9yaXR5IG9mIGNvdW50cmllcywgd2hlcmUgdGhleSBhcmUgZGVwZW5kZW50LiANCg0KTm93ICoqdGhlIG1haW4gYWltIG9mIHZpc3VhbGl6YXRpb24gcGFydCoqIGlzIHRvIHJlYWxseSBzZWUsIGNvbXBhcmUgdGhlIHJlc3VsdHMgd2l0aCBncmFwaHMsIGtub3cgaW50ZXJlc3RpbmcgZmFjdHMgYWJvdXQgb3VyIGFuZCBvdGhlciBjb3VudHJpZXMgYW5kIG1ha2Ugc3VyZSBvZiB0aGUgdHJ1dGggb2YgdGhlIGZpbmRpbmdzLg0KDQoNCg0KYGBge3J9DQpyZXF1aXJlKGdncGxvdDIpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCmxpYnJhcnkocGxvdGx5KQ0KDQpsaWJyYXJ5KGRnb2YpIA0KbGlicmFyeSgncGxvdC5tYXRyaXgnKQ0KDQpgYGANCg0KDQojIyBNYXRyaXggZm9yIHRlbmRlbmN5IG9mIE1lYW4sIE1vZGUsIE1lYWRpYW4gb2YgbGlmZSBleHBlY3RhbmN5IG9mIHRoZSBjb3VudHJpZXMNCg0KIyMjIyBEYXRhIGhhdmUgYmVlbiBjb2xsZWN0ZWQgdGhyb3VnaCAzMC01MCB5ZWFycw0KDQoNCkFjY29yZGluZyB0byB0aGlzIG1hdHJpeCB3ZSBjYW4gc2VlIGdlbmVyYWwgdGVuZGVuY3kgb2YgbGlmZSBleHBlY3RhbmN5IG9mIHRoZSBjb3VudHJpZXMgYW5kIHBsYWNlIHRoZW0gYnkgdmFsdWUgb2YgdGhpcyBpbmRpY2F0b3Ioc3RhcnRpbmcgZnJvbSBsb25nZXN0KToNCkphcGFuLCBVU0EsIFVrcmFpbmUsIFRhamlraXN0YW4sIEhhaXRpLCBNYWxpDQoNCmBgYHtyfQ0KDQoNCmdldF9tb2RlIDwtIGZ1bmN0aW9uKHYpIHsNCiAgIHVuaXF2IDwtIHVuaXF1ZSh2KQ0KICAgdW5pcXZbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHYsIHVuaXF2KSkpXQ0KfQ0KDQoNCmZpbGVuYW1lcyA8LSBjKCdkYXRhL2RhdGFfdXNhLmNzdicsICdkYXRhL2RhdGFfamFwYW4uY3N2JywNCiAgICAgICAgICAgICAgICdkYXRhL2RhdGFfdWtyYWluZS5jc3YnLCAnZGF0YS9kYXRhX3RhamlraXN0YW4uY3N2JywNCiAgICAgICAgICAgICAgICdkYXRhL2RhdGFfbWFsaS5jc3YnLCAnZGF0YS9kYXRhX2hhaXRpLmNzdicpDQoNCmNvdW50cnlfbmFtZXMgPC0gYygiVVNBIiwgIkphcGFuIiwgIlVrcmFpbmUiLCAiVGFqaWtpc3RhbiIsICJNYWxpIiwgIkhhaXRpIikNCmZlYXR1cmVzIDwtIGMoIl9fX19fTWVhbl9fX19fIiwgIl9fX19fTW9kZV9fX19fIiwgIl9fX19fTWVkaWFuX19fX18iKQ0KDQpjb3VudHJpZXNfbWF0cml4IDwtIG1hdHJpeCgwLCBucm93PWxlbmd0aChjb3VudHJ5X25hbWVzKSwgbmNvbD1sZW5ndGgoZmVhdHVyZXMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1uYW1lcz1saXN0KGNvdW50cnlfbmFtZXMsIGZlYXR1cmVzKSkNCg0KIyBjcmVhdGUgZ2VuZXJhbCBkYXRhIGZyYW1lIGZvciBlYXNpZXIgdmlzdWFsaXphdGlvbg0KZm9yIChpIGluIDE6bGVuZ3RoKGZpbGVuYW1lcykpIHsNCiAgZGYgPC0gcmVhZC5jc3YoZmlsZSA9IGZpbGVuYW1lc1tpXSkNCiAgZGZbImNvdW50cnkiXSA8LSBjb3VudHJ5X25hbWVzW2ldDQogIA0KICBjb3JyZWxhdGVkX2RmIDwtIGRmWywgYygibGlmZV9leHBlY3RhbmN5IiwgImhlYWx0aF9leHBlbmRpdHVyZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJ3YWdlZF93b3JrZXJzIiwgICJnZHAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZW1wbG95bWVudF9yYXRpbyIsICJleHBlbnNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImNvdW50cnkiKV0NCiAgDQogIGlmIChpID09IDEpIHsNCiAgICBnZW5lcmFsX2RmIDwtIGNvcnJlbGF0ZWRfZGYNCiAgfQ0KICBlbHNlIHsNCiAgICBnZW5lcmFsX2RmIDwtIHJiaW5kKGdlbmVyYWxfZGYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRlZF9kZikgDQogIH0NCiAgDQogICMgY2xlYXIgYSBjb2x1bW4gZnJvbSBOYU4gdmFsdWVzDQogIGZpbHRlcmVkX2xpc3QgPC0gbmEub21pdChjb3JyZWxhdGVkX2RmJGxpZmVfZXhwZWN0YW5jeSkNCiAgDQogIGNvdW50cmllc19tYXRyaXhbaSwgMV0gPSBtZWFuKGZpbHRlcmVkX2xpc3QpDQogIGNvdW50cmllc19tYXRyaXhbaSwgMl0gPSBnZXRfbW9kZShzYXBwbHkoZmlsdGVyZWRfbGlzdCwgRlVOPXJvdW5kKSkNCiAgY291bnRyaWVzX21hdHJpeFtpLCAzXSA9IG1lZGlhbihmaWx0ZXJlZF9saXN0KQ0KfQ0KDQp3cml0ZS5jc3YoZ2VuZXJhbF9kZiwgImRhdGEvZ2VuZXJhbF9kZi5jc3YiLCByb3cubmFtZXM9RkFMU0UpDQoNCnByaW50KGNvdW50cmllc19tYXRyaXgpDQoNCmBgYA0KDQojIyBCb3hwbG90cyBmb3IgY29tcGFyaXNvbiBvZiBkaWZmZXJlbnQgZmVhdHVyZXMNCg0KIyMjIyBQbG90bHkgbGlicmFyeSBhbHNvIGdpdmVzIHlvdSBhbiBvcHBvcnR1bml0eSB0byB6b29tIGluIGFuZA0KIyMjIyBob3ZlciBvdmVyIHRoZSBjdXJzb3Igb24gdGhlIGJveHBsb3QgYW5kIHNlZSB0aGUgcmVhbCBudW1iZXJzICAoPuKAv+KXoCninIwNCg0KDQpPbiB0aGUgYmVsb3cgcGxvdHMgd2UgY2FuIHNlZSB0aGF0ICoqaW4gdGhlIG1ham9yaXR5IG9mIHRoZSBjb3VudHJpZXMqKiBMaWZlIGV4cGVjdGFuY3kgKipyZWFsbHkgY29ycmVzcG9uZHMqKiB0byBvdXIgZmVhdHVyZXMuIE91ciBib3hwbG90cyBzaG93IE1pbiwgUTEsIE1lZGlhbiwgUTMgYW5kIE1heCBjaGFyYWN0ZXJpc3RpY3MuDQpJbiBzb21lIGNhc2VzLCBmb3IgZXguIFVTQSBoYXMgdGhlIGJpZ2dlc3QgSGVhbHRoIGV4cGVuZGl0dXJlLCBidXQgaXQgZG9lcyBub3QgaGF2ZSB0aGUgbG9uZ2VzdCBsaWZlIGV4cGVjdGFjeSAoaXQgd2FzIGFsc28gZm91bmQgb3V0IGluIHByZWRpY3Rpb25zIG9mIG91ciBsaW5lYXIgcmVncmVzc2lvbiBmb3IgdGhpcyBmZWF0dXJlIGFuZCBVU0EpDQoNCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoY291bnRyeSwgbGlmZV9leHBlY3RhbmN5KSkgKw0KICBnZ3RpdGxlKCJMaWZlIGV4cGVjdGFuY3kgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJZZWFycyIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KYA0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoY291bnRyeSwgaGVhbHRoX2V4cGVuZGl0dXJlKSkgKw0KICBnZ3RpdGxlKCJIZWFsdGggZXhwZW5kaXR1cmUgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5ID0gIkhlYWx0aCBleHBlbmRpdHVyZSIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIHdhZ2VkX3dvcmtlcnMpKSArDQogIGdndGl0bGUoIldhZ2VkIHdvcmtlcnMgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5ID0gIiUgb2YgcG9wdWxhdGlvbiIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIGdkcCkpICsNCiAgZ2d0aXRsZSgiR0RQIG9mIGRpZmZlcmVudCBjb3VudHJpZXMiKSArDQogIGxhYnMoeSA9ICJHRFAgcGVyIGNhcGl0YSIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIGV4cGVuc2UpKSArDQogIGdndGl0bGUoIkVtcGxveW1lbnQgcmF0aW8gb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSIlIG9mIHBvcHVsYXRpb24iKSArDQogIGdlb21fYm94cGxvdChhZXMoY29sb3IgPSBjb3VudHJ5LCBmaWxsID0gY291bnRyeSksIGFscGhhPS41KQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIGV4cGVuc2UpKSArDQogIGdndGl0bGUoIkV4cGVuc2Ugb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5ID0gIkV4cGVuc2UiKSArDQogIGdlb21fYm94cGxvdChhZXMoY29sb3IgPSBjb3VudHJ5LCBmaWxsID0gY291bnRyeSksIGFscGhhPS41KQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KDQojIyBQbG90cyBmb3IgY29tcGFyaXNvbiBvZiBkaWZmZXJlbnQgZGVuc2l0aWVzDQoNCiMjIyMgRm9yIGNsZWFyIHVuZGVyc3RhbmRpbmcsIGlmIGdyYXBoIGlzIGNsb3NlciB0byB0aGUgcmlnaHQgcGFydCwNCiMjIyMgc28gdGhlIGZlYXR1cmUgZm9yIHN1Y2ggY291bnRyeSBpcyBiaWdnZXIgOj0pDQoNCg0KQWxzbyBsaWtlIHByZXZpb3VzbHksIG9uIHRoZSBiZWxvdyBwbG90cyB3ZSBjYW4gc2VlIHRoYXQgKippbiB0aGUgbWFqb3JpdHkgb2YgdGhlIGNvdW50cmllcyoqIExpZmUgZXhwZWN0YW5jeSAqKnJlYWxseSBjb3JyZXNwb25kcyoqIHRvIG91ciBmZWF0dXJlcy4gTm93IHdlIGV4cGxvcmUgdGhlIGRlbnNpdHkgb2YgZGlmZmVyZW50IGZlYXR1cmVzIG9mIHRoZSBjb3VudHJpZXMuDQoNCkFmdGVyIGl0cyBpbnZlc3RpZ2F0aW5nIHdlIHVuZGVyc3RhbmQgdGhhdCBjb3VudHJpZXMgd2l0aCBoaWdoIGxldmVsIG9mIGVjb25vbWljIGRldmVsb3BtZW50IGhhdmUgcGFzc2VkIGEgbG9uZyB3YXkgb2YgaW1wcm92ZW1lbnQgYW5kIG1ha2UgaXQgd2l0aCBzbWFsbCBzdGVwcywgYnV0IHBlcmlvZGljYWxseS4gT24gdGhlIG90aGVyIGhhbmQsIGNvdW50cmllcyB3aXRoIGxlc3MgbGV2ZWwgb2YgZGV2ZWxvcG1lbnQgY2FuIHN0YXkgd2l0aCB0aGUgc2FtZSBpbmRpY2F0b3JzIG9mIHNvbWUgZmVhdHVyZXMgdGhyb3VnaCB0aGUgeWVhcnMuDQoNCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGxpZmVfZXhwZWN0YW5jeSwgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJMaWZlIGV4cGVjdGFuY3kgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJMaWZlIGV4cGVjdGFuY3kiKQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGhlYWx0aF9leHBlbmRpdHVyZSwgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJIZWFsdGggZXhwZW5kaXR1cmUgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJIZWFsdGggZXhwZW5kaXR1cmUiKQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KDQpgYGB7cn0NCnAgPC0gZ2dwbG90KGdlbmVyYWxfZGYsIGFlcyh4ID0gd2FnZWRfd29ya2VycywgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJXYWdlZCB3b3JrZXJzIG9mIGRpZmZlcmVudCBjb3VudHJpZXMiKSArDQogIGxhYnMoeT0iRGVuc2l0eSIsIHggPSAiV2FnZWQgd29ya2VycyIpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCiMjIyMgWW91IGNhbiB6b29tIGluIGlmIHlvdSB3YW50IHRvIGxvb2sgY2xvc2VyIGF0IHNvbWUgcGxvdHMNCg0KVVNBIGFuZCBKYXBhbiBoYXZlIHRoZSBiaWdnZXN0IHZhbHVlcyBvZiB0aGlzIHBhcmFtZXRlci4NCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGdkcCwgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJHRFAgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJHRFAgcGVyIGNhcGl0YSIpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCiMjIyMgWW91IGNhbiB6b29tIGluIGluIGNhc2UgeW91IHdhbnQgdG8gbG9vayBjbG9zZXIgYXQgc29tZSBwbG90cw0KDQoNClVTQSBhbmQgSmFwYW4gaGF2ZSB0aGUgYmlnZ2VzdCB2YWx1ZXMgb2YgdGhpcyBwYXJhbWV0ZXIuDQoNCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGVtcGxveW1lbnRfcmF0aW8sIGZpbGwgPSBjb3VudHJ5KSkrDQogIGdlb21fZGVuc2l0eShhZGp1c3Q9MS41LCBhbHBoYT0uNCkgKyANCiAgZ2d0aXRsZSgiRW1wbG95bWVudCByYXRpbyBvZiBkaWZmZXJlbnQgY291bnRyaWVzIikgKw0KICBsYWJzKHk9IkRlbnNpdHkiLCB4ID0gIkVtcGxveW1lbnQgcmF0aW8iKSArDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtNSwgNjUpKQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KDQpIZXJlIHdlIGFjdHVhbGx5IHNlZSB0aGF0IHBhcnRseSBkdWUgdG8gbGFyZ2UgYW1vdW50IG9mIGV4cGVuc2UgVWtyYWluZSBoYXMgbGVzcyBsaWZlIGV4cGVjdGFuY3kgdGhhdCBVU0Egb3IgSmFwYW4gOj0pDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKHggPSBleHBlbnNlLCBmaWxsID0gY291bnRyeSkpKw0KICBnZW9tX2RlbnNpdHkoYWRqdXN0PTEuNSwgYWxwaGE9LjQpICsgDQogIGdndGl0bGUoIkV4cGVuc2Ugb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJFeHBlbnNlIikNCg0KZ2dwbG90bHkocCkNCg0KYGBgDQoNCg0KDQoNCg0KIyMgRXhwbG9yaW5nIGlmIGRhdGEgb2YgTGlmZSBleHBlY3RhbmN5IG9mIFVrcmFpbmUgZm9sbG93IG9uZSBvZiB0aGUgc3RhbmRhcmQgZGlzdHJpYnV0aW9ucw0KDQoNCkFmdGVyIGV4cGxvcmluZyB0aGUgcmVzdWx0cyBvZiBLb2xtb2dvcm92LVNtaXJub3YgdGVzdCB3ZSBjYW4gc2VlIHRoYXQgb3VyIGRhdGEgZm9sbG93IGluIHRoZSBtYWpvcml0eSAod2UgbWFkZSBleHBlcmltZW50cyBmb3IgaXQpICoqbm9ybWFsIGRpc3RyaWJ1dGlvbioqIHdpdGggbWVhbiA9IG1lYW4oY291bnRyeV9kZlwkbGlmZV9leHBlY3RhbmN5KSBhbmQgc2QgPSBzZChjb3VudHJ5X2RmXCRsaWZlX2V4cGVjdGFuY3kpLiBIb3dldmVyLCB1bmlmb3JtIGRpc3RyaWJ1dGlvbiB3aXRoIG1pbiA9IG1pbihjb3VudHJ5X2RmXCRsaWZlX2V4cGVjdGFuY3kpIGFuZCBtYXggPSBtYXgoY291bnRyeV9kZlwkbGlmZV9leHBlY3RhbmN5KSBhbHNvIGlzIHByZXR0eSBjbG9zZS4NCg0KSXQgd2FzIHByb3ZlZCB3aXRoIGJlbG93IHZpc3VhbGl6YXRpb25zLg0KDQoNCmBgYHtyfQ0KbGlicmFyeSh0b2xlcmFuY2UpDQpjb3VudHJ5X2RmIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX3VrcmFpbmUuY3N2JykNCg0KZmlsdGVyZWRfbGlzdCA8LSBuYS5vbWl0KGNvdW50cnlfZGYkbGlmZV9leHBlY3RhbmN5KQ0KDQpsZW5fbGlzdCA8LSBsZW5ndGgoZmlsdGVyZWRfbGlzdCkNCg0KY29tcGFyZV9ub3JtIDwtIHJub3JtKGxlbl9saXN0LCBtZWFuPW1lYW4oZmlsdGVyZWRfbGlzdCksIA0KICAgICAgICAgICAgICAgICAgICAgIHNkPXNkKGZpbHRlcmVkX2xpc3QpKQ0KY29tcGFyZV9leHAgPC0gcjJleHAobGVuX2xpc3QsIHNoaWZ0PW1pbihmaWx0ZXJlZF9saXN0KSkNCmNvbXBhcmVfdW5pZiA8LSBydW5pZihsZW5fbGlzdCwgbWluID0gbWluKGZpbHRlcmVkX2xpc3QpLCBtYXggPSBtYXgoZmlsdGVyZWRfbGlzdCkpDQoNCmtzLnRlc3QoZmlsdGVyZWRfbGlzdCwgY29tcGFyZV9ub3JtKQ0Ka3MudGVzdChmaWx0ZXJlZF9saXN0LCBjb21wYXJlX2V4cCkNCmtzLnRlc3QoZmlsdGVyZWRfbGlzdCwgY29tcGFyZV91bmlmKQ0KDQpgYGANCmBgYHtyfQ0KbGlicmFyeShsYXR0aWNlKQ0KbGlicmFyeShsYXR0aWNlRXh0cmEpDQoNCnZhbHMgPC0gZGF0YS5mcmFtZShmZWF0dXJlPWZpbHRlcmVkX2xpc3QsDQogICAgICAgICAgICAgICAgICAgbm9ybV9kaXN0cj1jb21wYXJlX25vcm0pDQoNCmVjZGZwbG90KH4gZmVhdHVyZSArIG5vcm1fZGlzdHIsIGRhdGE9dmFscywgYXV0by5rZXk9bGlzdChzcGFjZT0ncmlnaHQnKSkNCg0KYGBgDQpgYGB7cn0NCnZhbHMgPC0gZGF0YS5mcmFtZShmZWF0dXJlPWZpbHRlcmVkX2xpc3QsDQogICAgICAgICAgICAgICAgICAgZXhwX2Rpc3RyPWNvbXBhcmVfZXhwKQ0KDQplY2RmcGxvdCh+IGZlYXR1cmUgKyBleHBfZGlzdHIsIGRhdGE9dmFscywgYXV0by5rZXk9bGlzdChzcGFjZT0ncmlnaHQnKSkNCg0KYGBgDQpgYGB7cn0NCnZhbHMgPC0gZGF0YS5mcmFtZShmZWF0dXJlPWZpbHRlcmVkX2xpc3QsDQogICAgICAgICAgICAgICAgICAgdW5pZl9kaXN0cj1jb21wYXJlX3VuaWYpDQoNCmVjZGZwbG90KH4gZmVhdHVyZSArIHVuaWZfZGlzdHIsIGRhdGE9dmFscywgYXV0by5rZXk9bGlzdChzcGFjZT0ncmlnaHQnKSkNCg0KYGBgDQoNCiMgQ29uY2x1c2lvbg0KDQpTbywgd2hhdCB3ZSBjYW4gc2VlIGlzIHRoYXQgZm9yIGV2ZXJ5IGNvdW50cnkgdGhlIGltcG9ydGFuY2Ugb2Ygc29tZSBmZWF0dXJlcyBtYXkgZGlmZmVyLCB0YWtlIGZvciBleGFtcGxlICoqVGVjaCoqLCB0aGlzIGZlYXR1cmUgaXMgdmVyeSBzaWduaWZpY2FudCBpbiAiVGVjaC1jb3VudHJpZXMiIHN1Y2ggYXMgSmFwYW4gYW5kLCBhcyB3ZSBjYW4gc2VlLCB0aGVyZSBpcyBzb21lIGxpbmVhciByZWxhdGlvbiBiZXR3ZWVuIExpZmUgRXhwZWN0YW5jeSBhbmQgVGVjaCBpbmR1c3RyeSB0aGVyZSwgYnV0IG5vdCBmb3Igb3RoZXIgY291bnRyaWVzLiBUaGUgc2FtZSB3ZSBjYW4gc2F5IGFib3V0ICoqQmluZGluZyBDb3ZlcmFnZSoqIGFzIGluIEhpZ2gtSW5jb21lIENvdW50cmllcyB0aGlzIHBhcmFtZXRlciBpcyBhbHdheXMgYWxtb3N0IHRoZSBzYW1lLCB3aGljaCBkb2Vzbid0IHNob3cgYW55IGxpbmVhciByZWxhdGlvbiwgYnV0IHRoaXMgZG9lcyBub3QgbWVhbiB0aGF0IGl0IGlzIGluc2lnbmlmaWNhbnQgKGF0IGxlYXN0IG5vdCBmb3IgY291bnRyaWVzLCBidXQgZm9yIG91ciBtb2RlbCkuDQoNCldlIGhhdmUgY292ZXJlZCB3aGF0IHBhcmFtZXRlcnMgZG8gbm90IGdpdmUgdXMgYW55IHBvc3NpYmlsaXR5IHRvIGVzdGltYXRlIExpZmUgRXhwZWN0YW5jeSwgbGV0J3MgdGFsdCBhYm91dCB0aGUgcGFyYW1ldGVycywgdGhhdCBoYXZlIHNob3duIHVzIGEgZ29vZCBsaW5lYXIgcmVsYXRpb24uIFRoZXNlIGFyZToNCg0KMS4gKipXYWdlZCBXb3JrZXJzIFJhdGlvKiogKDAuNzcgZ29vZG5lc3Mgb2YgZml0IG9uIGF2ZXJhZ2UpDQoyLiAqKkdEUCoqICgwLjc1IGdvb2RuZXNzIG9mIGZpdCBvbiBhdmVyYWdlKQ0KMy4gKipIZWFsdGggRXhwZW5kaXR1cmUqKiAoMC43MiBnb29kbmVzcyBvZiBmaXQgb24gYXZlcmFnZSkNCjQuICoqRW1wbG95bWVudCBSYXRpbyArIEV4cGVuc2UqKiAoMC42IGdvb2RuZXNzIG9mIGZpdCBvbiBhdmVyYWdlKQ0KDQpPZiBjb3Vyc2UsIHRoZXNlIGVzdGltYXRpb25zIGFyZSBub3QgdmVyeSBhY2N1cmF0ZSBiZWNhdXNlIG9mIHRoZSBsYWNrIG9mIGRhdGEsIGJ1dCBhdCBsZWFzdCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgaXMgc29tZSByZWxhdGlvbiBiZXR3ZWVuIHRoZXNlIHBhcmFtZXRlcnMgYW5kIGxpZmUgZXhwZWN0YW5jeSBhbmQgaXQncyBjbGVhciBhcyBldmVyeXRoaW5nIHJlZHVjZXMgdG8gaWYgY291bnRyeSBjYW4gcHJvdmlkZSBpdHMgcmVzaWRlbnRzIHdpdGggd29yaywgbWVkaWNpbmUgYW5kIGdvb2QgZmluYW5jZSBjYXBpdGFsICh3aGljaCBkZXBlbmRzIG9uIGpvYiksIHRoZW4gdGhvc2UgcGVvcGxlIGNhbiBjb3ZlciBhbGwgdGhlaXIgbmVlZCB0byBsaXZlIGxvbmcgYW5kIGhlYWx0aHkgbGlmZS4NCg==